From 62eb5d0358b4b753bf0902b2bb712ad3a36f25f3 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Kristian=20H=C3=B8gsberg?= Date: Wed, 20 Mar 2013 22:34:03 -0400 Subject: [PATCH] wayland: Add a cursor cache We avoid creating a new GdkCursor object every time _gdk_wayland_display_get_cursor_for_name/type() is called. --- gdk/wayland/gdkcursor-wayland.c | 73 ++++++++++++++++++++++++++++++++ gdk/wayland/gdkdisplay-wayland.c | 2 + gdk/wayland/gdkdisplay-wayland.h | 1 + gdk/wayland/gdkprivate-wayland.h | 2 + 4 files changed, 78 insertions(+) diff --git a/gdk/wayland/gdkcursor-wayland.c b/gdk/wayland/gdkcursor-wayland.c index ce6456515c..198753e193 100644 --- a/gdk/wayland/gdkcursor-wayland.c +++ b/gdk/wayland/gdkcursor-wayland.c @@ -65,6 +65,68 @@ G_DEFINE_TYPE (GdkWaylandCursor, _gdk_wayland_cursor, GDK_TYPE_CURSOR) static guint theme_serial = 0; +struct cursor_cache_key +{ + GdkCursorType type; + const char *name; +}; + +static void +add_to_cache (GdkWaylandDisplay *display, GdkWaylandCursor *cursor) +{ + display->cursor_cache = g_slist_prepend (display->cursor_cache, cursor); + + g_object_ref (cursor); +} + +static gint +cache_compare_func (gconstpointer listelem, + gconstpointer target) +{ + GdkWaylandCursor *cursor = (GdkWaylandCursor *) listelem; + struct cursor_cache_key* key = (struct cursor_cache_key *) target; + + if (cursor->cursor.type != key->type) + return 1; /* No match */ + + /* Elements marked as pixmap must be named cursors + * (since we don't store normal pixmap cursors + */ + if (key->type == GDK_CURSOR_IS_PIXMAP) + return strcmp (key->name, cursor->name); + + return 0; /* Match */ +} + +static GdkWaylandCursor* +find_in_cache (GdkWaylandDisplay *display, + GdkCursorType type, + const char *name) +{ + GSList* res; + struct cursor_cache_key key; + + key.type = type; + key.name = name; + + res = g_slist_find_custom (display->cursor_cache, &key, cache_compare_func); + + if (res) + return (GdkWaylandCursor *) res->data; + + return NULL; +} + +/* Called by gdk_wayland_display_finalize to flush any cached cursors + * for a dead display. + */ +void +_gdk_wayland_display_finalize_cursors (GdkWaylandDisplay *display) +{ + g_slist_foreach (display->cursor_cache, (GFunc) g_object_unref, NULL); + g_slist_free (display->cursor_cache); +} + static void gdk_wayland_cursor_finalize (GObject *object) { @@ -281,6 +343,15 @@ _gdk_wayland_display_get_cursor_for_name (GdkDisplay *display, g_return_val_if_fail (GDK_IS_DISPLAY (display), NULL); + private = find_in_cache (wayland_display, GDK_CURSOR_IS_PIXMAP, name); + if (private) + { + /* Cache had it, add a ref for this user */ + g_object_ref (private); + + return (GdkCursor*) private; + } + private = g_object_new (GDK_TYPE_WAYLAND_CURSOR, "cursor-type", GDK_CURSOR_IS_PIXMAP, "display", display, @@ -319,6 +390,8 @@ _gdk_wayland_display_get_cursor_for_name (GdkDisplay *display, private->buffer = wl_cursor_image_get_buffer(cursor->images[0]); + add_to_cache (wayland_display, private); + return GDK_CURSOR (private); } diff --git a/gdk/wayland/gdkdisplay-wayland.c b/gdk/wayland/gdkdisplay-wayland.c index e244118c3b..4193d53971 100644 --- a/gdk/wayland/gdkdisplay-wayland.c +++ b/gdk/wayland/gdkdisplay-wayland.c @@ -204,6 +204,8 @@ gdk_wayland_display_finalize (GObject *object) { GdkWaylandDisplay *display_wayland = GDK_WAYLAND_DISPLAY (object); + _gdk_wayland_display_finalize_cursors (display_wayland); + /* Keymap */ if (display_wayland->keymap) g_object_unref (display_wayland->keymap); diff --git a/gdk/wayland/gdkdisplay-wayland.h b/gdk/wayland/gdkdisplay-wayland.h index fb284e323c..ce2082de06 100644 --- a/gdk/wayland/gdkdisplay-wayland.h +++ b/gdk/wayland/gdkdisplay-wayland.h @@ -65,6 +65,7 @@ struct _GdkWaylandDisplay struct wl_data_device_manager *data_device_manager; struct wl_cursor_theme *cursor_theme; + GSList *cursor_cache; GSource *event_source; diff --git a/gdk/wayland/gdkprivate-wayland.h b/gdk/wayland/gdkprivate-wayland.h index 6f07059b79..480108ec46 100644 --- a/gdk/wayland/gdkprivate-wayland.h +++ b/gdk/wayland/gdkprivate-wayland.h @@ -53,6 +53,8 @@ GdkKeymap *_gdk_wayland_keymap_new_from_fd (uint32_t format, uint32_t fd, uint32_t size); struct xkb_state *_gdk_wayland_keymap_get_xkb_state (GdkKeymap *keymap); +void _gdk_wayland_display_finalize_cursors (GdkWaylandDisplay *display); + GdkCursor *_gdk_wayland_display_get_cursor_for_type (GdkDisplay *display, GdkCursorType cursor_type); GdkCursor *_gdk_wayland_display_get_cursor_for_name (GdkDisplay *display, -- 2.30.2